[Amazon SageMaker] CloudWatch Logsからcross_entropyやmAPのスコアを取得して一覧してみました
1 はじめに
CX事業本部の平内(SIN)です。
Amazon SageMaker(以下、SageMaker)の組み込みアルゴリズムでは、トレーニング、評価、および検証メトリクスを自動で計算して発行しています。
そして、トレーニングの結果は、コンソールからグラフとして確認することもできます。
しかし、この機能は、トレーニングジョブ単位のため、増分学習などで、複数回に分けたジョブを俯瞰することは出来ません。また、グラフは時系列であり、epoch回数との関連を見ることは難しいと思います。
今回は、CloudWatch Logsから学習の進行の目安となる行を抜き出し、複数に分けたジョブも俯瞰できるようにしてみました。
2 CloudWatch Logs
SageMakerによるトレーニングのログでは、Epochごとに、cross_entropy (loass)、smooth_l1(loss) 及び、mAPの(score)の値がメトリックスとして出力されています。
ここで、cross_entropyの減少などは、モデルが十分に学習されているかどうかの目安になります。
以下は、CloudWatch Logsから"epoch="という文字列でフィルタした出力例です。
epoch=0, batch=113 train cross_entropy <loss>=(1.4180332298993061) epoch=0, batch=113 train smooth_l1 <loss>=(0.6312907669714584) epoch=0, validation mAP <score>=(0.06950676633142766) epoch=1, batch=113 train cross_entropy <loss>=(1.1537240667553887) epoch=1, batch=113 train smooth_l1 <loss>=(0.5577520465688716) epoch=1, validation mAP <score>=(0.5435744797706069) epoch=2, batch=113 train cross_entropy <loss>=(0.882764700426082) epoch=2, batch=113 train smooth_l1 <loss>=(0.4858317924157635) epoch=2, validation mAP <score>=(0.7965334703107155) epoch=3, batch=113 train cross_entropy <loss>=(0.7305765847092396) epoch=3, batch=113 train smooth_l1 <loss>=(0.3920442789711215) epoch=3, validation mAP <score>=(0.9287345323256168) epoch=4, batch=113 train cross_entropy <loss>=(0.6735127696786309) epoch=4, batch=113 train smooth_l1 <loss>=(0.32503517851902314) epoch=4, validation mAP <score>=(0.983961968966895) epoch=5, batch=113 train cross_entropy <loss>=(0.6005626925608006) epoch=5, batch=113 train smooth_l1 <loss>=(0.2669418989158258) epoch=5, validation mAP <score>=(0.9913976509103337)
3 集計
上記のログを対象に、cross_entropy、smooth_l1及び、mAPの数値を抜き出して、一覧にするコードです。 ジョブ名は、配列で指定するようになっており、複数回に分けてトレーニングしたログも纏めて処理できます。
from boto3.session import Session import re # Job名(複数指定可能) jobs = ['object-detection-2020-04-24-23-53-37-140/algo-1-1587772559'] session = Session(profile_name='developer') client = session.client('logs') group_name = '/aws/sagemaker/TrainingJobs' # "epoch="が含まれるログ抽出する filter_pattern = 'epoch=' response = client.filter_log_events( logGroupName=group_name, logStreamNames=jobs, limit=300, filterPattern=filter_pattern, ) # cross_entropy, smooth_l1, mAPにそれぞれ振り分ける cross_entropy = [] smooth_l1 = [] mAP = [] for event in response["events"]: message = event["message"] print(message) # debug # ()の中を抜き出す m = re.search(r'\(.*\)', message) num = m.group().replace('(','').replace(')','') # 視認しやすいように、少数第三位で丸める num = round(float(num), 3) if('cross_entropy' in message): cross_entropy.append(num) elif('smooth_l1' in message): smooth_l1.append(num) elif('mAP' in message): mAP.append(num) # 表示 print("epoch\tmAP\tsmooth_l1\tcross_entropy") print("-----------------------------------------") for i in range(len(mAP)): print("{}\t{}\t{}\t{}".format(i, mAP[i], smooth_l1[i], cross_entropy[i]))
出力結果です。なお、ここで表示されているEpochは、ログが抽出したものではなく、単純に0からの連番になっているため、ストリームを複数指定したは、増分学習のログという前提です。
epoch mAP smooth_l1 cross_entropy ----------------------------------------- 0 0.07 0.631 1.418 1 0.544 0.558 1.154 2 0.797 0.486 0.883 3 0.929 0.392 0.731 4 0.984 0.325 0.674 5 0.991 0.267 0.601 6 0.991 0.239 0.547 7 0.991 0.214 0.502 8 0.992 0.198 0.465 9 0.992 0.177 0.449 10 0.994 0.159 0.419
4 最後に
今回は、複数に分けて行ったトレーニングの状況をEpochと共に俯瞰してみました。次回は、HPO(ハイパーパラメータ最適化)アルゴリズムで学習が進行する状況を、この一覧で確認してみたいと考えています。